// 用接口定义函数的形状

const fn: (a: number, b: number) => number = (a: number, b: number): number => {
  return a + b
}

interface IFn {
  (a: number, b: number): number
}
const fn1: IFn = (a: number, b: number): number => {
  return a + b
}

// 可选参数  ? 
function fn2 (a: number, b: number, c?: number): number {
  return a + b
}

// 默认值  
function fn3 (a: number = 10, b: number = 20, c?: number): number {
  return a + b
}

// 如果参数是可选参数，不能给它设置默认值
function fn4 (a: number, b: number, c?: number = 30): number {
  return a + b + c
}
// 剩余参数
function push(array, ...items) {
  items.forEach(function(item) {
    array.push(item)
  })
}

let a = []
push(a, 1, 2, 3)
console.log(a)

// 重载  ----   联合类型情况
// 重载允许一个函数接受不同数量或类型的参数时，作出不同的处理。
// 比如，我们需要实现一个函数 reverse，输入数字 123 的时候，输出反转的数字 321，输入字符串 'hello' 的时候，输出反转的字符串 'olleh'。
function reverse (x: string | number): number | string {
  if (typeof x === "number") {
    return Number(x.toString().split('').reverse().join(''))
  } else {
    return x.split('').reverse().join('')
  }
}
// 这样有一个缺点，就是不能够精确的表达，输入为数字的时候，输出也应该为数字，输入为字符串的时候，输出也应该为字符串。
// 这时，我们可以使用重载定义多个 reverse 的函数类型：

function reverse1 (x: number): number
function reverse1 (x: string): string
function reverse1 (x: string | number): string | number {
  if (typeof x === "number") {
    return Number(x.toString().split('').reverse().join(''))
  } else {
    return x.split('').reverse().join('')
  }
}
// 重复定义了多次函数 reverse，前几次都是函数定义，最后一次是函数实现
// TypeScript 会优先从最前面的函数定义开始匹配，
// 所以多个函数定义如果有包含关系，需要优先把精确的定义写在前面。
